#ifndef PULSE_OPTICAL_H_
#define PULSE_OPTICAL_H_

#include <functional>
#include <queue>
#include <vector>

#include "Algorithm.h"
#include "Graph.h"

class Pulse_optical : public Algorithm {
 public:
    Pulse_optical() {}
    ~Pulse_optical();
    void SetupTopology(Graph* graph) override;
    Path FindPath(const Flow& flow) override;
    void Check();
    void GetInterationsNum(){
        std::cout<<num_iterations_;
    };

private:
    std::vector<std::vector<Lable>> L_perm; // permanent labels
    std::vector<std::vector<Lable>> L_clear;
    struct cmp{
        bool operator() (const Lable& l1, const Lable& l2){
            return l1.weight> l2.weight;
        }
    } ;// 小堆顶
    std::vector<std::priority_queue<Lable, std::vector<Lable>, cmp>> Q_tent;//tentative labels
    std::vector<std::priority_queue<Lable, std::vector<Lable>, cmp>> Q_clear;
    std::vector<bool> Visited; // 记录是否已经访问过

 private:

    struct PulseInfo {
        PulseInfo() {}
        void Clear() {
            min_cost_path.clear();
            min_delay_path.clear();
            max_units_path.clear();
            random_rep_path.clear();
        }
        Path min_cost_path;
        Path min_delay_path;
        Path max_units_path;
        Path random_rep_path;
    };

    // Helper functions
    std::vector<int> Intersection(std::vector<int> v1, std::vector<int> v2);
    bool Judge(std::vector<int> v1,std::vector<int> v2);

    void Dfs(NodeId u, Path& path);
    bool check(NodeId u, int cost, int delay);
    bool update(NodeId u, const Path& path, double p);

    void Generic_Dijkstra(NodeId end, int* node_to_dst_dis, bool flag);
    void Relax_cost(Link* e, Lable l);
    void Relax_delay(Link* e, Lable l);
    bool Lable_Judge(Lable& l1, Lable& l2);
    // Variables for initialization
    int* cost_map_;
    int* delay_map_;
    int num_nodes_;

    // Variables for pulse search
    bool* visited_;
    PulseInfo* info_;
    Flow flow_;
    int tmp_min_delay;
    std::vector<Path> results_;
    int num_iterations_;
};

#endif  // PULSE_OPTICAL_H_